import * as path from 'path';
import * as fs from 'fs';
import { Logger } from '../../../../src/logger/Logger';
import { FuzzGroupLocator } from './FuzzGroupLocator';

/**
 * Fuzz BUILD.gn 更新器
 * 负责更新父级 BUILD.gn 文件，注册新的 Fuzzer
 */
export class FuzzBuildGNUpdater {
    /**
     * 智能更新父级 BUILD.gn 文件（新版：支持跨目录查找 group）
     * 
     * @param projectRoot 项目根目录
     * @param fuzzerDir Fuzzer 完整目录路径
     * @param testTargetName 测试目标名称
     * @returns { success: boolean; groupPath?: string; message: string }
     */
    public static smartUpdateParentBuildGN(
        projectRoot: string,
        fuzzerDir: string,
        testTargetName: string
    ): { success: boolean; groupPath?: string; message: string } {
        // 步骤1：查找所有 group("fuzztest")
        const allGroups = FuzzGroupLocator.findAllFuzzGroups(projectRoot);

        if (allGroups.length === 0) {
            Logger.warn(`[FuzzBuildGNUpdater] ⚠️  未找到任何 group("fuzztest")，将创建新的 group`);
            
            // 在 fuzzerDir 的上级目录创建 group
            const fuzzerParentDir = path.dirname(fuzzerDir);
            const groupGnPath = path.join(fuzzerParentDir, 'BUILD.gn');
            
            const created = this.createParentBuildGNIfNotExists(fuzzerParentDir);
            if (created) {
                // 立即注册到新创建的 group
                const fuzzerDirName = path.basename(fuzzerDir);
                return this.registerToGroup(groupGnPath, `./${fuzzerDirName}`, testTargetName);
            }
            
            return {
                success: false,
                message: '无法创建 group("fuzztest")'
            };
        }

        // 步骤2：推荐最合适的 group
        const recommendedGroup = FuzzGroupLocator.recommendBestGroup(fuzzerDir, allGroups);

        if (!recommendedGroup) {
            return {
                success: false,
                message: '无法推荐合适的 group'
            };
        }

        Logger.info(`[FuzzBuildGNUpdater] 📍 选择 group: ${recommendedGroup.relativePath}`);
        Logger.info(`[FuzzBuildGNUpdater]    原因: ${recommendedGroup.reason}`);

        // 步骤3：计算相对路径
        const relativePath = FuzzGroupLocator.calculateRelativePath(fuzzerDir, recommendedGroup.gnPath);
        const depPath = FuzzGroupLocator.formatDepPath(relativePath, testTargetName);

        // 步骤4：注册到 group
        return this.registerToGroup(recommendedGroup.gnPath, relativePath, testTargetName);
    }

    /**
     * 注册 Fuzzer 到指定的 group BUILD.gn
     */
    private static registerToGroup(
        groupGnPath: string,
        relativePath: string,
        testTargetName: string
    ): { success: boolean; groupPath?: string; message: string } {
        const depPath = FuzzGroupLocator.formatDepPath(relativePath, testTargetName);

        if (!fs.existsSync(groupGnPath)) {
            return {
                success: false,
                message: `Group BUILD.gn 不存在: ${groupGnPath}`
            };
        }

        try {
            let content = fs.readFileSync(groupGnPath, 'utf-8');
            
            // 检查是否已经注册
            if (content.includes(depPath)) {
                Logger.info(`[FuzzBuildGNUpdater] ℹ️  ${depPath} 已存在于 ${groupGnPath}`);
                return {
                    success: true,
                    groupPath: groupGnPath,
                    message: `已存在于 group（跳过）`
                };
            }

            // 查找 group("fuzztest") { deps = [ ... ] }
            const groupRegex = /group\s*\(\s*["']fuzztest["']\s*\)\s*\{[^}]*deps\s*=\s*\[([^\]]*)\]/s;
            const match = content.match(groupRegex);

            if (match) {
                const depsContent = match[1];
                const updatedDeps = depsContent.trim()
                    ? `${depsContent.trim()},\n    "${depPath}"`
                    : `\n    "${depPath}"\n  `;
                
                content = content.replace(
                    groupRegex,
                    (fullMatch) => fullMatch.replace(
                        /deps\s*=\s*\[[^\]]*\]/,
                        `deps = [${updatedDeps}]`
                    )
                );

                fs.writeFileSync(groupGnPath, content, 'utf-8');
                Logger.info(`[FuzzBuildGNUpdater] ✅ 已更新 ${groupGnPath}，添加 ${depPath}`);
                
                return {
                    success: true,
                    groupPath: groupGnPath,
                    message: `已注册到 ${path.relative(process.cwd(), groupGnPath)}`
                };
            } else {
                Logger.warn(`[FuzzBuildGNUpdater] ⚠️  未找到 group("fuzztest") 定义，无法自动注册`);
                return {
                    success: false,
                    message: '未找到 group("fuzztest") 定义'
                };
            }
        } catch (error: any) {
            Logger.error(`[FuzzBuildGNUpdater] ❌ 更新 ${groupGnPath} 失败: ${error.message || error}`);
            return {
                success: false,
                message: `更新失败: ${error.message}`
            };
        }
    }

    /**
     * 兼容旧版 API（已弃用）
     * @deprecated 使用 smartUpdateParentBuildGN 代替
     */
    public static updateParentBuildGN(
        fuzzTestDir: string,
        fuzzerDirName: string,
        testTargetName: string
    ): boolean {
        const parentBuildGnPath = path.join(fuzzTestDir, 'BUILD.gn');

        if (!fs.existsSync(parentBuildGnPath)) {
            Logger.warn(`[FuzzBuildGNUpdater] 父级 BUILD.gn 不存在: ${parentBuildGnPath}`);
            return false;
        }

        const relativePath = `./${fuzzerDirName}`;
        const result = this.registerToGroup(parentBuildGnPath, relativePath, testTargetName);
        return result.success;
    }

    /**
     * 提取 group 中的 test target 名称
     * @param buildGnContent BUILD.gn 内容
     * @returns test target 名称，如 "DaudiosourcemanagerFuzzerTest"
     */
    public static extractTestTargetName(buildGnContent: string): string | null {
        // 匹配 group("fuzztest") { ... deps = [ ":XXXFuzzTest" ] ... }
        const match = buildGnContent.match(/group\s*\(\s*["']fuzztest["']\s*\)[^}]*deps\s*=\s*\[\s*["']:([^"']+)["']/);
        if (match) {
            return match[1];
        }

        // 备用：匹配 ohos_fuzztest("XXXFuzzTest")
        const fuzzTestMatch = buildGnContent.match(/ohos_fuzztest\s*\(\s*["']([^"']+)["']\s*\)/);
        if (fuzzTestMatch) {
            return fuzzTestMatch[1];
        }

        return null;
    }

    /**
     * 创建父级 BUILD.gn 文件（如果不存在）
     * @param fuzzTestDir test/fuzztest 目录
     * @returns 创建是否成功
     */
    public static createParentBuildGNIfNotExists(fuzzTestDir: string): boolean {
        const parentBuildGnPath = path.join(fuzzTestDir, 'BUILD.gn');

        if (fs.existsSync(parentBuildGnPath)) {
            return true;
        }

        try {
            const currentYear = new Date().getFullYear();
            const content = `# Copyright (c) ${currentYear} Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import("//build/test.gni")

group("fuzztest") {
  testonly = true
  deps = []
}
`;
            fs.writeFileSync(parentBuildGnPath, content, 'utf-8');
            Logger.info(`[FuzzBuildGNUpdater] ✅ 已创建父级 BUILD.gn: ${parentBuildGnPath}`);
            return true;
        } catch (error: any) {
            Logger.error(`[FuzzBuildGNUpdater] ❌ 创建父级 BUILD.gn 失败: ${error.message || error}`);
            return false;
        }
    }
}

